package com.wxxymaker.service.impl;

import com.blade.kit.EncrypKit;
import com.wxxymaker.model.dao.UserDao;
import com.wxxymaker.model.entity.User;
import com.wxxymaker.service.UserService;
import com.wxxymaker.utils.web.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDate;
import java.util.*;

/**
 * @Author: Soft
 * @Date: 2018/5/7 17:14
 * @Desc: 用户业务层实现
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao dao;

    @Override
    @Transactional
    public User add(User user) {
        user.setPassword(EncrypKit.md5(user.getPassword()));
        user.setRegTime(new Date());
        return dao.save(user);
    }

    @Override
    @Transactional
    public User delete(Integer id) {
        User one = dao.findOne(id);
        if (null != one) {
            dao.delete(one);
        }
        return one;
    }

    @Override
    @Transactional
    public int deleteByUsername(String username) {
        return dao.deleteAllByUsername(username);
    }

    @Override
    @Transactional
    public boolean change(User user) {
        Integer id = user.getId();
        if (null != id && id > 0) {
            User one = (User) dao.findOne(user.getId()).extend(user);
            return null != dao.saveAndFlush(one);
        }
        return false;
    }

    @Override
    public User getOne(Integer id) {
        return dao.findOne(id);
    }

    /**
     * 根据学号判断是不是已经离校
     */
    private void checkIsLeaveSchool(String username) {
        Integer enter = Integer.valueOf(username.substring(0, 4));
        LocalDate now = LocalDate.now();
        int year = now.getYear();
        if (year - enter >= 4 && (year - enter != 4 || now.getMonthValue() > 7)) {
            throw ServiceException.msg("你已离校，无法使用！");
        }
    }

    @Override
    public boolean checkUser(User user) {
        User one = dao.findByUsernameAndPassword(user.getUsername(),
                EncrypKit.md5(user.getPassword()));
        // 是学生才判断是不是毕业了
        if (one != null && User.PostDim.STU == one.getPost()) {
            this.checkIsLeaveSchool(user.getUsername());
        }
        return null != one && one.getId() > 0;
    }

    @Override
    public User getByUsername(String username) {
        User user = dao.findByUsername(username);
        // 是学生才判断是不是毕业了
        if (user != null && User.PostDim.STU == user.getPost()) {
            this.checkIsLeaveSchool(username);
        }
        return user;
    }

    @Override
    public List<User> getByLikeName(String name) {
        return dao.findByRealNameLike("%"+name+"%");
    }

    @Override
    public BackStatus getBack(User user) {
        BackStatus bs = new BackStatus();
        User su = this.getByUsername(user.getUsername());
        if (su != null) {
            if (su.getTel().equals(user.getTel())) {
                if (user.getPassword() != null) {
                    su.setPassword(EncrypKit.md5(user.getPassword()));
                    if (this.change(su)) {
                        bs.setMsg("找回成功").setSuccess(true);
                    }
                } else {
                    bs.setSuccess(false).setMsg("请输入合法的密码！");
                }
            } else {
                bs.setSuccess(false).setMsg("电话号码错误！");
            }
        } else {
            bs.setSuccess(false).setMsg("用户不存在！");
        }
        return bs;
    }

    @Override
    public Page<User> page(Integer pageNo, Integer size, Map<String, Object> map) {
        Specification<User> specification = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> ps = new LinkedList<>();
                if (map != null) {
                    map.forEach((k, v)->{
                        if ("post".equals(k) && (int) v > 0) {
                            ps.add(cb.equal(root.get("post"), v));
                        }
                        if ("name".equals(k) && !"".equals(v)) {
                            ps.add(cb.like(root.get("realName"), "%" + v + "%"));
                        }
                    });
                }
                query.where(ps.toArray(new Predicate[ps.size()]));
                return null;
            }
        };
        Pageable pageable = new PageRequest(pageNo - 1, size,
                new Sort(Sort.Direction.DESC, "regTime"));
        return dao.findAll(specification, pageable);
    }

    @Override
    public Page<User> page(Integer pageNo, Integer size, Integer post) {
        Map<String, Object> map = new HashMap<>();
        if (post != null && post != 0) {
            map.put("post", post);
        }
        return this.page(pageNo, size, map);
    }

    @Override
    @Transactional
    public boolean addNum(Integer id) {
        return dao.addNum(id) > 0;
    }

    @Override
    public long count(Integer... post) {
        Specification<User> specification = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                if (post.length > 0 && post[0] > 0) {
                    query.where(cb.equal(root.get("post"), post[0]));
                }
                return null;
            }
        };
        return dao.count(specification);
    }
}
